Skip to content

Top Down game tutorial


Basic Top down tutorial

Published: Mon Jun 02 2025 02:43:09 GMT+0000 (Coordinated Universal Time)

Top down Tutorial

This tutorial will have you use GMAP map builder to make a very simple top down game, but it'll give a demonstration of core concepts such as collision in top down views, playing audio based on actions, and related concepts.

For this you will need to import the latest version of the add on, then import these copy right free sounds collected from freesound.org, or collect your own!

Copy right free sound download

Experimental tutorial

The steps were automatically generated using an addon that recorded my actions as I made the example, I then removed mistakes and added comments and wrote the instructions.

So make sure to give feedback on what you think of it as it helps me create them much faster!

As usual there will be a details section before the instructions section, then commented code for you to read and paste in.

Creating our Player

Details

First we will create our player. Our player will move around, have positional listening to hear other objects, play a sound when running into walls, play a sound when heading towards a wall, and play a sound based on if moving or not moving.

Our player will be a CharacterBody2D scene with motion mode set to Floating, meaning it's not meant to be impacted by gravity.

Our player will have an AudioListener2D node set to active, so it will calculate directional audio from this object.

Via code we will add several AudioStreamPlayer that will control our movement, proximity alarm, and running into wall sounds.

Via code we will add a ShapeCast2D to be used to warn the player of collisions. A shape cast is like a ray cast, with with width. A ray cast is a single pixel wide line from point A to point B. But if the player is more than a pixel wide, a ray cast might not collide with a wall that our player will. So that is why we create a shape cast with the same width as our player.

We will use a function that comes with the addons to add a CollisionShape2D and give it a small colored square.

So import the addon template, copy in the the sounds folder, and follow along!

Instructions

Create a new scene. CTRL+N, CTRL+A, then select: CharacterBody2D

Set focus to CharacterBody2D in scene tab (CTRL+F8).

Press enter on CharacterBody2D and rename it to Player.

Add node AudioListener2D as child of Player(CharacterBody2D Node) CTRL+A to open node create menu.

Go to inspector, ctrl+f6 to get to inspector tab, ctrl+U to inspector categories.

Property current set to true

Set focus to CharacterBody2D in scene tab (CTRL+F8).

Attach a script to Player(CTRL+Equal Sign)

Script 1

extends CharacterBody2D
#https://docs.godotengine.org/en/stable/tutorials/physics/using_character_body_2d.html

#How many pixels per second our character should move. Feel free to change this around!
const SPEED = 200.0 
#audio players
var step_sfx = AudioStreamPlayer.new()
var bonk = AudioStreamPlayer.new()
var impact_alert = AudioStreamPlayer.new()
#impact detector
var impact_detect = ShapeCast2D.new()

var collide

const DRIVING_SOUND = preload("res://sounds/driving_sound.mp3")
const BONK = preload("res://sounds/bonk.mp3")
const IMPACT_ALERT = preload("res://sounds/impact_alert.wav")

func _ready():
	motion_mode = CharacterBody2D.MOTION_MODE_FLOATING
	#making a smaller hit box for our player, making it red. GM is a addon from the extension, not part of godot.
	GM.create_collide_rect(32,32,self,true,Color.RED)
	#Using a GMAP added function here as well to map key board keys to also work as well as arrow keys as directions.
	#Arrow keys by default are part of ui_ in all godot projects
	GM.add_event("ui_left",KEY_A)
	GM.add_event("ui_right",KEY_D)
	GM.add_event("ui_up",KEY_W)
	GM.add_event("ui_down",KEY_S)
	#assinging the streams the imported audio files
	step_sfx.stream = DRIVING_SOUND
	bonk.stream = BONK
	impact_alert.stream = IMPACT_ALERT
	#Created objects won't impact the game until added as a child, they are in the void until then.
	add_child(step_sfx)
	add_child(bonk)
	add_child(impact_alert)
	#Change this to adjust how loud hitting a wall is.
	bonk.volume_db = -10
	#Configuring out shapecast, which will check for any impacts on our length so we can warn the player.
	#First we are saying to use a shape the same size as our player for the checking. Which is a 32x32 rectangle
	var collide_shape = RectangleShape2D.new()
	collide_shape.size = Vector2(32,32)
	#We are saying to detect 64 pixels out, then in our movement code we rotate the impact detector to be checking the direction the player is moving.
	impact_detect.target_position = Vector2(0,64)
	impact_detect.shape = collide_shape
	add_child(impact_detect)
	
func _process(delta):
	#checks each step where to move
	if Input.is_action_pressed("ui_left"):
		velocity = Vector2(-SPEED,0)
		impact_detect.rotation_degrees =90
	elif Input.is_action_pressed("ui_right"):
		velocity = Vector2(SPEED,0)
		impact_detect.rotation_degrees =-90
	elif Input.is_action_pressed("ui_up"):
		velocity = Vector2(0,-SPEED)
		impact_detect.rotation_degrees =180
	elif Input.is_action_pressed("ui_down"):
		velocity = Vector2(0,SPEED)
		impact_detect.rotation_degrees =0
	else:
		velocity = (Vector2(0,0))
	#This is a built in function of the characterbody2d that uses the velocity to move around
	#Because we set the motion mode to floating, it will change how certain things function.
	collide = move_and_collide(velocity * delta)
	motor_volume()
	impact_warning()

#function that will make it so as we move our little motor will get louder, and always be looping. 
func motor_volume():
	#keep looping
	if step_sfx.playing == false:
		step_sfx.play()
	if velocity == (Vector2(0,0)):
		#How loud our engine will be while "idle"
		step_sfx.volume_db = -40
	else:
		#change this until your volume is good indicator it is moving, I start with it rather soft.
		step_sfx.volume_db = -20
	#If we hit a wall and we're not already playing bonk, play bonk.
	if collide and bonk.playing == false:
		bonk.play()
#function to use the built in GMAP in game map. Pressing escape will pull up a map, allowing you to confirm everything is working or help navigate
func _unhandled_input(_event):
	if Input.is_action_just_pressed("ui_cancel"):
		get_parent().gmap_view_map(global_position,11,"ui_cancel")
#function that is checking if need to play alarm sound
func impact_warning():
	#simple check if our shape cast is hitting anything, to start playing if we detect a collision and not already playing
	if impact_detect.is_colliding():
		if impact_alert.playing == false:
			impact_alert.play()
	else:
		impact_alert.stop()

Creating our wall

Details

Our wall is going to be very simple and one you are familiar with. A StaticBody2d with a script attached to give it collision.

Instructions

Create a new scene. CTRL+N, CTRL+A, then select: StaticBody2D

Set focus to StaticBody2D in scene tab (CTRL+F8).

Press enter on StaticBody2D and rename it to Wall.

Attach a script to Wall(CTRL+Equal Sign)

Script 2

extends StaticBody2D

func _ready():
	#Just make a black 64 x 64 box.
	GM.create_collide_rect(64,64,self,true,Color.BLACK)


Game room

Details

Next we are creating our GMAP node, that will hold our walls and player. After creating this, you can press F2 and test it out, but we will have one more game object we want to add in the tutorial. Our game room is very simple though, not even needing a script.

Instructions

Create a new scene. CTRL+N, CTRL+A, then select: GMAP

Set focus to GMAP in scene tab (CTRL+F8).

Press enter on GMAP and rename it to Game.

Go to inspector, ctrl+f6 to get to inspector tab, ctrl+U to inspector categories.

Property node_size set to 64

Property rows set to 8

Property columns set to 8


Interactable

Details

The final item for this mini tutorial will be a coin using an Area2D that plays a shimmering noise when the player is close using a AudioStreamPlayer2D node, the play a pickup sound when the player collides with it using a a standard AudioStreamPlayer. We trigger the pickup code using a signal that fires off attached code when the player enters the collision area.

Area2Ds are special because they do not prevent collision, they simply report on it, so can be used for just about anything. Could make it so the player takes damage when they enter or get hit by it, could have it be if they stand on one and press space they go to a new scene as they entered a door, or could be it plays audio as the Area2d represents the area around an npc that you are able to speak to them.

Instructions

Create a new scene. CTRL+N, CTRL+A, then select: Area2D

Set focus to Area2D in scene tab (CTRL+F8).

Press enter on Area2D and rename it to Pickup.

Attach a script to Pickup(CTRL+Equal Sign)

Script 3

extends Area2D

var shiny = AudioStreamPlayer2D.new()
var pickup = AudioStreamPlayer.new()

const PICKUP = preload("res://sounds/pickup.mp3")
const SHINY = preload("res://sounds/shiny.mp3")

var picked_up = 0

func _ready():
	
	GM.create_collide_rect(32,32,self,true,Color.YELLOW)
	pickup.stream = PICKUP
	shiny.stream = SHINY
	add_child(pickup)
	add_child(shiny)
	shiny.max_distance = 500
	shiny.panning_strength = 20
	shiny.play()
	
func _on_body_entered(body: Node2D) -> void:
	if picked_up == 0:
		picked_up = 1
		pickup.play()
		shiny.stop()
		
func _process(_delta):
	if picked_up == 0 and shiny.playing == false:
		shiny.play()
	

Final steps

CTRL+F9 to go to node tab

Attached body_entered(body:Node2D) by pressing enter twice to connect to our script

Build your map!

In standard game dev, you would be testing each piece as you went, but to get you to where you can try it out we did everything one go, but now is where you can experiment.

Go to the Game scene, then press F2 to go to the accessible map builder that came with the GMAP project template, and start building a map! Simply type in the name of an object, and an instance will be created at that location. Here's a small demo map I made, where I walled off the sides, made some columns, then put a coin down.

In the build your first game tutorial it's also covered how you can assign variables to specific instances, so if you create a sign post you don't have to create a new sign post scene for every one, simply create one, then assign its text from here.

Let me know what you think of the tutorial, and good luck!